package org.androidpn.server.xmpp.handler;

import java.util.Date;
import java.util.List;

import org.androidpn.server.entity.Friend;
import org.androidpn.server.entity.FriendGroup;
import org.androidpn.server.entity.Role;
import org.androidpn.server.service.FriendGroupService;
import org.androidpn.server.service.FriendService;
import org.androidpn.server.service.RoleService;
import org.androidpn.server.service.ServiceLocator;
import org.androidpn.server.xmpp.UnauthorizedException;
import org.androidpn.server.xmpp.packet.FriendPacket.Operation;
import org.androidpn.server.xmpp.session.ClientSession;
import org.dom4j.Element;
import org.jivesoftware.smack.util.StringUtils;
import org.xmpp.packet.IQ;
import org.xmpp.packet.PacketError;

/**
 * This class is to handle the TYPE_IQ jabber:iq:roster protocol.
 * 
 * @author Sehwan Noh (devnoh@gmail.com)
 */
public class IQFriendHandler extends IQHandler {

	private static final String NAMESPACE = "jabber:iq:friend";

	private FriendService friendService = null;

	private FriendGroupService friendGroupService = null;

	private RoleService roleService = null;

	/**
	 * Constructor.
	 */
	public IQFriendHandler() {
		friendService = (FriendService) ServiceLocator
				.getService(ServiceLocator.FRIEND_SERVICE);
		friendGroupService = (FriendGroupService) ServiceLocator
				.getService(ServiceLocator.FRIEND_GROUP_SERVICE);
		roleService = (RoleService) ServiceLocator
				.getService(ServiceLocator.ROLE_SERVICE);
	}

	/**
	 * Handles the received IQ packet.
	 * 
	 * @param packet
	 *            the packet
	 * @return the response to send back
	 * @throws UnauthorizedException
	 *             if the user is not authorized
	 */
	public IQ handleIQ(IQ packet) throws UnauthorizedException {
		IQ reply = null;

		ClientSession session = sessionManager.getSession(packet.getFrom());

		try {
			Element query = packet.getChildElement();
			reply = IQ.createResultIQ(packet);
			String operationStr = query.elementText("operation");
			if (operationStr != null && !operationStr.equals("")) {
				Operation operation = Operation.valueOf(operationStr);
				switch (operation) {
				case addFriendByNickname:
					addFriendByNickname(reply, query);
					break;
				case deleteFriendByNickname:
				default:
					reply.setError(PacketError.Condition.feature_not_implemented);
					break;
				}
			} else {
				reply = null;
			}
		} catch (Exception e) {
			log.error(e.getMessage());
			reply.setError(PacketError.Condition.feature_not_implemented);
		}
		if (reply != null) {
			session.process(reply);
		}
		return null;
	}

	/**
	 * 通过昵称添加好友
	 * 
	 * @param reply
	 * @param query
	 */
	private void addFriendByNickname(IQ reply, Element query) {
		Long friendGroupId = Long.valueOf(query.elementText("friendGroupId"));
		FriendGroup friendGroup = friendGroupService.find(friendGroupId);
		if (friendGroup == null) {
			reply.setError(PacketError.Condition.bad_request);
			return;
		}

		Friend friend = Friend.fromXML(StringUtils.unescapeNode(query
				.elementText("friend")));

		String nickname = friend.getRole().getNickname();
		Role role = roleService.getRoleByNickname(nickname);
		if (role == null) {
			reply.setError(PacketError.Condition.item_not_found);
			return;
		}
		if (friendGroup.getRole().getId().equals(role.getId())) {
			reply.setError(PacketError.Condition.forbidden);
			return;
		}
		Long myRoleId = friendGroup.getRole().getId();
		Long friendRoleId = role.getId();
		if (friendService.findFriend(myRoleId, friendRoleId) != null) {
			reply.setError(PacketError.Condition.conflict);
			return;
		}

		// 给自己添加上好友
		friend.setId(null);
		friend.setCreateDate(new Date());
		friend.setModifyDate(new Date());
		friend.setRemark(null);
		friend.setFriendGroup(friendGroup);
		friend.setIsPassed(true);
		friend.setRole(role);
		friendService.save(friend);
		// 给对方添加自己为好友
		Friend toFriend = new Friend();
		toFriend.setId(null);
		toFriend.setCreateDate(new Date());
		toFriend.setModifyDate(new Date());
		toFriend.setRemark(null);
		List<FriendGroup> friendGroups = friendGroupService
				.getFriendGroupByRoleID(role.getId());
		for (FriendGroup friendGroup2 : friendGroups) {
			if (!friendGroup2.getIsBlacklist()) {
				toFriend.setFriendGroup(friendGroup2);
				break;
			}
		}
		toFriend.setIsPassed(false);
		toFriend.setRole(friendGroup.getRole());
		friendService.save(toFriend);
	}

	public String getNamespace() {
		return NAMESPACE;
	}
}
